require 'find'
require 'yaml'
require 'map_config_dialog'
require 'dgo/tile_map/map_loader'
require 'map_editor/model'
require 'event_editor/io'

class MapNavigator < Gtk::ScrolledWindow
  def initialize(main_container, height)
    super()
    @main_container = main_container
    
    # Tree View
    @model = Gtk::TreeStore.new(String, String)
    @treeview = Gtk::TreeView.new(@model)
    @treeview.reorderable = true
    @treeview.headers_visible = false
    @treeview.set_height_request(height)
    selection = @treeview.selection
    self.add_with_viewport(@treeview)
    
    # Menu
    menu = Gtk::Menu.new
    items = {}
    
    items[:new] = Gtk::MenuItem.new("create new map")
    items[:new].signal_connect('activate') { self.create_new_map(selection.selected) }

    menu.append(items[:new])
    
    items[:edit] = Gtk::MenuItem.new("edit")
    items[:edit].sensitive = true
    items[:edit].signal_connect('activate') do
      self.edit_map(selection.selected)

    end
    
    menu.append(items[:edit])

    items[:delete] = Gtk::MenuItem.new("Delete")
    items[:delete].sensitive = true
    items[:delete].signal_connect('activate') { delete_map(selection.selected) }
    menu.append(items[:delete])
    

    items[:copy] = Gtk::MenuItem.new("copy")
    items[:copy].sensitive = true
    items[:copy].signal_connect('activate'){p "Copy" }
    menu.append(items[:copy])
    

    items[:paste] = Gtk::MenuItem.new("paste")
    items[:paste].sensitive = false
    items[:paste].signal_connect('activate'){p "Paste" }
    menu.append(items[:paste])

    menu.show_all
    

    # Tree View Events    
    renderer = Gtk::CellRendererText.new
    column = Gtk::TreeViewColumn.new("Map Navigator", renderer, {
                                       :text => 0   
                                     })
    
    @treeview.append_column(column)
    
    pressed_button = nil
    pressed_button_event = nil
    
    @treeview.signal_connect("button-press-event") do |item, event|
      if event.kind_of?(Gdk::EventButton) && event.button  == 3
        if @model.iter_first
          menu.popup(nil, nil, event.button, event.time)
        else
          self.popup_map_config_dialog(nil)
        end
      end      
      
      if event.button  == 1
        pressed_button = :left
        pressed_button_event = event
      end

      false
    end

    selection.signal_connect('changed') do
      iter = selection.selected
      if iter
        if iter[1]
          filename = iter[1]
          map_model = MapEditor::IO.load(filename)
          event_model = EventEditor::IO.load(map_model)
          @main_container.load_map(map_model, event_model)
          @main_container.show_all
        else
          @main_container.clear_map_container
          @main_container.show_all
        end
      end
    end
  end
  
  def delete_map(iter)
    dialog = Gtk::Dialog.new('Interactive Dialog',
           $window,
           Gtk::Dialog::MODAL |
           Gtk::Dialog::DESTROY_WITH_PARENT,
           ["OK", Gtk::Dialog::RESPONSE_OK],
           ["Cancel", Gtk::Dialog::RESPONSE_CANCEL]
           )
          
    dialog.window_position = Gtk::Window::POS_MOUSE
    vbox = Gtk::VBox.new(false, 5)
    vbox.add(Gtk::Label.new("Are you really going to delete?"))
    dialog.vbox.pack_start(vbox, false, false, 10)
    vbox.show_all
    response = dialog.run
    
    if response == Gtk::Dialog::RESPONSE_OK
      @model.remove(iter)
      self.save
    end
    
    dialog.destroy
  end
  
  def edit_map(iter)
    model = @main_container.map_model
    
    panorama_id = ""
    panorama_id = File.basename(model.panorama.texture_id) if model.panorama
    self.popup_map_config_dialog(iter, 
      {
        :map_id => model.map_id, 
        :name => iter[0], 
        :width => model.tile_x_count, 
        :height => model.tile_y_count,
        :base_chipset => model.base_chipset.name, 
        :anime_chipset => model.anime_chipset.name,
        :panorama => panorama_id
      }
    )
  end
  
  def create_new_map(iter)
    model = @main_container.map_model
    self.popup_map_config_dialog(iter, {})
  end

  def get_latest_map_id
    i = 0
    map_path = $res.data_path + "map/map"
    while true
      fn = map_path + i.to_s + ".yaml"
      unless File.exist?(fn)
        return "map#{i}"
      end
      i += 1
    end
  end
  
  def popup_map_config_dialog(iter, edit_option = {})

    map_id = get_latest_map_id
      
    if edit_option.empty?
      edit_option = {:map_id => map_id}.merge(edit_option)
      edit = false
    else
      edit = true
    end
      
    MapConfigDialog.show($window, edit_option) do |name, width, height, base_chipset_name, anime_chipset_name, panorama_name|

      if edit
        # change size if it is changed
        @main_container.map_panel.set_map_size(width, height)
 
        @main_container.map_model.panorama = DGO::TileMap::MapLoader.load_panorama($res.root_path, panorama_name)
        @main_container.map_model.base_chipset = DGO::TileMap::MapLoader.load_base_chipset($res.root_path, base_chipset_name, $config.grid_width, $config.grid_height)
        @main_container.set_palet_panels(@main_container.map_model)
        iter[0] = name
        
      else
        model = MapEditor::Model.new(map_id, DGO::TileMap::MapLoader.generate_blank_map($res.root_path, width, height, $config.grid_width, $config.grid_height, 2, base_chipset_name, anime_chipset_name))
        MapEditor::IO.save_map(model)
        EventEditor::IO.save_new_event(map_id)
        self.add_item(name, map_id, iter)
      end
      self.save
    end
  end
  
  def show
    selection.selected
  end

  def add_item(name, map_id, parent)
    new_item = @model.append(parent)
    new_item[0] = name
    new_item[1] = map_id
  end
  
  # def add_items(root_path, search_path, parent, func)
    # new_item = nil
    # Dir::glob("#{search_path}*.yaml").each do |path|
      # new_item = @model.append(parent)
      # new_item[0] = File.basename(path).split(".")[0]
      # new_item[1] = path.sub(root_path, "").split(".")[0]
      # new_item[2] = func
      
      # dir_path = search_path + new_item[0]
      # if File.directory?(dir_path)
        # self.add_items(root_path, dir_path + "/", new_item, func)
      # end
    # end
  # end
  
  def load
    @model.clear

    filename = "#{$res.data_path}map/tree_view.yaml"

    return unless File.exists?(filename)
    
    arr = []
    File.open(filename, "r") do |f|
      arr = YAML::load(f.read)
    end

    load_iter_tree(arr, nil)

    self.show_all
    
    @treeview.selection.select_path(Gtk::TreePath.new(0))
  end
  
  def load_iter_tree(arr, parent)
    arr.each do |data|
      iter = @model.append(parent)
      iter[0] = data[0]
      iter[1] = data[1]
      load_iter_tree(data[2], iter) if data[2]
    end
  end
  
  def get_iter_tree(iter)
    return [] unless iter
    arr = []
    begin
      child = iter.has_child? ? get_iter_tree(iter.first_child) : nil
      arr << [iter[0], iter[1], child]
    end while iter.next!
    return arr
  end
  
  def save
    arr = self.get_iter_tree(@model.iter_first)
    str = arr.to_yaml
    File.open("#{$res.data_path}map/tree_view.yaml", "w+") do |f|
      f.write(str)
    end
  end
end